package com.fsoft.core.utils.qrcode;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QrCodeUtil {
	public static void createQrCode(OutputStream outputStream, String content, int qrCodeSize, String imageFormat) throws WriterException, IOException {
		BitMatrix bitMatrix = createQrCode(content, qrCodeSize);
		BufferedImage bfImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
		int width = bitMatrix.getWidth();
		if (qrCodeSize != width) {
			BufferedImage newBufferedImage = new BufferedImage(qrCodeSize, qrCodeSize, BufferedImage.TYPE_INT_ARGB);
			Graphics2D g2d = newBufferedImage.createGraphics();
			double scale = (float) qrCodeSize / width;
			g2d.scale(scale, scale);
			g2d.drawImage(bfImage, 0, 0, null);
			g2d.dispose();
			ImageIO.write(newBufferedImage, imageFormat, outputStream);
		} else {
			ImageIO.write(bfImage, imageFormat, outputStream);
		}
	}

	public static BitMatrix createQrCode(String content, int qrCodeSize, String imageFormat, String filePath) throws IOException, WriterException {
		File file = new File(filePath);
		if (!file.exists()) {
			file.createNewFile();
		}
		BitMatrix bitMatrix = createQrCode(content, qrCodeSize);
		MatrixToImageWriter.writeToFile(bitMatrix, imageFormat, file);
		return bitMatrix;

	}

	public static String readQrCode(InputStream inputStream) throws IOException {
		// 从输入流中获取字符串信息
		BufferedImage image = ImageIO.read(inputStream);
		// 将图像转换为二进制位图源
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
		QRCodeReader reader = new QRCodeReader();
		Result result = null;
		try {
			result = reader.decode(bitmap);
		} catch (ReaderException e) {
			e.printStackTrace();
		}
		if (result == null) {
			return null;
		}
		return result.getText();
	}

	public static BitMatrix createQrCode(String content, int qrCodeSize) throws UnsupportedEncodingException, WriterException {

		@SuppressWarnings({ "rawtypes", "unchecked" })
		Map<EncodeHintType, Object> hints = new HashMap(4);
		// 字符编码
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		// 容错等级 L、M、Q、H 其中 L 为最低,// H 为最高
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hints.put(EncodeHintType.MARGIN, 1);
		hints.put(EncodeHintType.MIN_SIZE, 35);
		MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
		BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hints);
		bitMatrix = deleteWhite(bitMatrix, qrCodeSize);
		return bitMatrix;
	}

	private static BitMatrix deleteWhite(BitMatrix bitMatrix, int qrCodeSize) {
		int[] rec = bitMatrix.getEnclosingRectangle();
		int left = rec[0];
		int width = rec[2] + 9;

		// 白边长度,白边长度不多不用处理
		if (left > 10) {
			BitMatrix newresBitMatrix = new BitMatrix(width, width);
			newresBitMatrix.clear();
			for (int i = 4; i < width; i++) {
				for (int j = 4; j < width; j++) {
					if (bitMatrix.get(i + left - 4, j + rec[1] - 4)) {
						newresBitMatrix.set(i, j);
					}
				}
			}
			return newresBitMatrix;
		}
		// BITMAP
		return bitMatrix;
	}
}
